﻿namespace Lilium.CSharp.Expressions.Substitutions

open System
open System.Linq.Expressions

type ISubstitution =
    abstract member GetExpression : 
        (Expression -> Expression)  // transformer
        -> Expression               // substitution method (TODO: current varsion only valid for the method call substitutions, make generic!)
        -> # Expression List        // substitution arguments 
        -> # Expression List        // substitution type arguments 
        -> Expression               // result expression

[<AbstractClass>]
[<AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)>]
type SubstitutionAttribute () =
    inherit Attribute ()
    abstract member GetExpression : (Expression -> Expression) -> Expression -> # Expression List -> # Expression List -> Expression
    interface ISubstitution with
        member self.GetExpression transformer meth args typeArgs = self.GetExpression transformer meth args typeArgs


module Utils =
    
    let internal substitutionCall () = failwith "Substitution function should not be called directly."